﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using TNCGameEngine.Content;

namespace SpaceAdventureLib.Universe
{
    [Serializable]
    public abstract class Collidable : Entity, ILoadable
    {

        #region "Properties"

        private Model model = null;
        public Model Model
        {
            get { return this.model; }
            set { this.model = value; }
        }

        private string modelName = string.Empty;
        protected string ModelName
        {
            get { return this.modelName; }
            set { this.modelName = value; }
        }

        public bool IsModelReady
        {
            get { return (this.model != null); }
        }

        #endregion

        #region "Variables"

        private ContentManager content = null;
        
        #endregion              

        #region "Methods"

        protected override void PreInitialize(Space space)
        {
            base.PreInitialize(space);
            this.content = space.Mission.Content;
        }

        public virtual List<AssetToLoad> GetAssetsToLoad()
        {
            List<AssetToLoad> list = new List<AssetToLoad>(1);
            list.Add(new AssetToLoad(this.modelName, typeof(Model)));
            return list;
        }

        public virtual void LoadContent(ContentLoader loader)
        {
            this.model = loader.GetContent<Model>(this.modelName);
        }

        public virtual void UnloadContent(SharedContentManager content)
        {
            content.UnloadSingleContent(this.model);
        }

        public static List<AssetToLoad> GetCommonAssetsToLoad()
        {
            return new List<AssetToLoad>();
        }

        public static void LoadCommonContent(ContentLoader loader)
        {
            // do nothing
        }

        public static void UnloadCommonContent(SharedContentManager content)
        {
            // do nothing
        }
                
        public virtual void Draw(Camera camera, GraphicsDevice graphics)
        {
            if (this.IsModelReady)
            {
                this.DrawModel(camera, this.model, this.World);
            }
        }
                
        /// <summary>
        /// Simple model drawing method. The interesting part here is that
        /// the view and projection matrices are taken from the camera object.
        /// </summary>        
        protected void DrawModel(Camera camera, Model model, Matrix world)
        {
            model.Draw(world, camera.View, camera.Projection);
        }


        protected void UpdateWorldMatrix()
        {
            Matrix m = Matrix.Identity;
            m.Forward = this.Forward;
            m.Up = this.Up;
            m.Right = this.Right;
            m.Translation = this.Location;
            this.World = m;            
        }

        public List<BoundingSphere> GetBoundingSpheres()
        {

            if (this.IsModelReady) { return null; }

            List<BoundingSphere> spheres = new List<BoundingSphere>(this.model.Meshes.Count);

            foreach (ModelMesh m in this.model.Meshes)
            {
                spheres.Add(m.BoundingSphere);
            }

            return spheres;

        }

        public bool IsColliding(Collidable c)
        {

            foreach (BoundingSphere s1 in this.GetBoundingSpheres())
            {
                foreach (BoundingSphere s2 in c.GetBoundingSpheres())
                {
                    if (s1.Intersects(s2))
                    {
                        return true;
                    }
                }
            }
            return false;

        }

        #endregion

                
    }
}
